﻿using System;
using ThoughtWorks.CruiseControl.Core.tasks.Conditions;
using ThoughtWorks.CruiseControl.Core.tasks.Conditions.DateTimeHelpers;
using Exortech.NetReflector;
using NUnit.Framework;
using Rhino.Mocks;
using ThoughtWorks.CruiseControl.Core;
using ThoughtWorks.CruiseControl.Core.Util;

namespace ThoughtWorks.CruiseControl.UnitTests.Core.Tasks.Conditions
{
    [TestFixture]
    public class timeTaskConditionTest
    {            
        MockRepository mocks = new MockRepository();
        IIntegrationResult _integrationResult;
        DateTimeProvider _dateTimeProvider;

        [TestFixtureSetUp]
        public void Setup()
        {
            _dateTimeProvider = mocks.StrictMock<DateTimeProvider>();
            Expect.Call(_dateTimeProvider.Now).Return(new DateTime(1972, 08, 27, 16, 30, 00)).Repeat.Any();
            
            _integrationResult = mocks.StrictMock<IIntegrationResult>();
            Expect.Call(_integrationResult.StartTime).Return(new DateTime(1972, 08, 27, 16, 20, 0)).Repeat.Any();
            Expect.Call(_integrationResult.EndTime).Return(new DateTime(1972, 08, 27, 16, 40, 0)).Repeat.Any();
            Modification[] objToReturn = new[] { new Modification() { ModifiedTime = new DateTime(1972, 08, 27, 16, 10, 0) } };
            Expect.Call(_integrationResult.Modifications).Return(objToReturn).Repeat.Any();

            mocks.ReplayAll();
        }

        [TestFixtureTearDown]
        public void TearDown()
        {
            mocks.VerifyAll();
        }

        [Test]
        [Description("XmlInterface Success")]
        [Category("interface")]
        public void timeTaskConditionTest_XmlInterface_Success(
            [Values("<timeCondition/>", "<timeCondition dayOfWeek=\"Weekend\" timeOfDay=\"09:00-19:00\" timeZone=\"GMT-1:00\" timeToEvaluate=\"now\"/>")] string xml
            )
        {
            NetReflectorTypeTable table = new NetReflectorTypeTable();
            table.Add(typeof(TimeTaskCondition));
            TimeTaskCondition result = NetReflector.Read(xml, table) as TimeTaskCondition;

            Assert.That(result, Is.Not.Null);
            Assert.That(result.Eval(_integrationResult), Is.True);
        }

        [Test]
        [Description("TimeToValidate success")]
        public void timeTaskConditionTest_TimeToValidate_success(
            [Values(TimeToEvaluate.now, TimeToEvaluate.buildStart, TimeToEvaluate.buildEnd, TimeToEvaluate.firstModification, TimeToEvaluate.lastModification)]
            TimeToEvaluate evaluate)
        {
            TimeTaskCondition condition = new TimeTaskCondition(_dateTimeProvider);
            condition.DayOfWeek = "weekend";
            condition.TimeOfDay = "16:00-17:00";
            condition.TimeToEvaluate = evaluate;
            Assert.That(condition.Eval(_integrationResult), Is.True);
        }

        [Test]
        [Description("TimezoneParsing")]
        [Category("Category")]
        public void timeTaskConditionTest_TimezoneParsing()
        {
            DateTime dateTime = new DateTime(2010, 3, 10, 10, 0, 0);
            TimeSpan baseOffset = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);

            Assert.That(DatetimeFunctions.getTimeZoneOffset("", dateTime), Is.EqualTo(new TimeSpan(0, 0, 0)));
            Assert.That(DatetimeFunctions.getTimeZoneOffset("current", dateTime), Is.EqualTo(new TimeSpan(0)));
            Assert.That(DatetimeFunctions.getTimeZoneOffset("GMT", dateTime), Is.EqualTo(baseOffset));

            Assert.That(DatetimeFunctions.ParseTimeZone("GMT"), Is.EqualTo(new TimeSpan(0)));
            Assert.That(DatetimeFunctions.ParseTimeZone("GMT+10"), Is.EqualTo(new TimeSpan(10,0,0)));
            Assert.That(DatetimeFunctions.ParseTimeZone("GMT+10:30"), Is.EqualTo(new TimeSpan(10,30,0)));
            Assert.That(DatetimeFunctions.ParseTimeZone("GMT-1"), Is.EqualTo(-new TimeSpan(1,0,0)));
            Assert.That(DatetimeFunctions.ParseTimeZone("GMT-10"), Is.EqualTo(-new TimeSpan(10,0,0)));
            Assert.That(DatetimeFunctions.ParseTimeZone("GMT-10:30"), Is.EqualTo(-new TimeSpan(10,30,0)));
        }

        [Test]
        [Description("InvalidValues ThrowArgumentException")]
        [Category("parsing")]
        public void TimePeriodTest_InvalidValues_ThrowArgumentException(
            [Values("gmt","gmt+24","GMT+-5","GMT5","GMT+10:10:10","GMT+10:61","GMT-13","GMT+13")]string value)
        {
            Assert.Throws<ArgumentException>(() => DatetimeFunctions.ParseTimeZone(value), value + " parsed as a valid value");
        }
    }
}
